package com.memorywords.utils;

import java.security.SecureRandom;
import java.util.Random;

public class RandomStringUtil {

    /**
     * 随机字符串生成工具类
     * 提供各种类型的随机字符串生成方法
     */


        // 字符集常量
        private static final String NUMERIC = "0123456789";
        private static final String ALPHA_LOWER = "abcdefghijklmnopqrstuvwxyz";
        private static final String ALPHA_UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        private static final String ALPHA = ALPHA_LOWER + ALPHA_UPPER;
        private static final String ALPHANUMERIC = ALPHA + NUMERIC;
        private static final String SAFE_ALPHANUMERIC = "23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz";
        private static final String ASCII_PRINTABLE = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";

        // 随机数生成器
        private static final Random RANDOM = new Random();
        private static final SecureRandom SECURE_RANDOM = new SecureRandom();

//        private RandomStringUtils() {
//            // 工具类，防止实例化
//        }

        /**
         * 生成指定长度的随机字符串（包含字母和数字）
         * @param count 字符串长度
         * @return 随机字符串
         */
        public static String random(int count) {
            return random(count, false, false);
        }

        /**
         * 生成指定长度的字母字符串
         * @param count 字符串长度
         * @return 随机字母字符串
         */
        public static String randomAlphabetic(int count) {
            return random(count, true, false);
        }

        /**
         * 生成指定长度的数字字符串
         * @param count 字符串长度
         * @return 随机数字字符串
         */
        public static String randomNumeric(int count) {
            return random(count, false, true);
        }

        /**
         * 生成指定长度的字母数字混合字符串
         * @param count 字符串长度
         * @return 随机字母数字字符串
         */
        public static String randomAlphanumeric(int count) {
            return random(count, true, true);
        }

        /**
         * 生成指定长度的安全字母数字混合字符串（排除易混淆字符）
         * @param count 字符串长度
         * @return 安全随机字符串
         */
        public static String randomSafeAlphanumeric(int count) {
            return random(count, SAFE_ALPHANUMERIC);
        }

        /**
         * 生成指定长度的ASCII可打印字符字符串
         * @param count 字符串长度
         * @return ASCII可打印字符串
         */
        public static String randomAscii(int count) {
            return random(count, ASCII_PRINTABLE);
        }

        /**
         * 使用安全随机数生成器生成指定长度的字母数字混合字符串
         * @param count 字符串长度
         * @return 安全随机字符串
         */
        public static String randomSecureAlphanumeric(int count) {
            return randomSecure(count, ALPHANUMERIC);
        }

        /**
         * 核心随机字符串生成方法
         * @param count 字符串长度
         * @param letters 是否包含字母
         * @param numbers 是否包含数字
         * @return 随机字符串
         */
        public static String random(int count, boolean letters, boolean numbers) {
            return random(count, 0, 0, letters, numbers);
        }

        /**
         * 高级随机字符串生成方法
         * @param count 字符串长度
         * @param start ASCII起始值
         * @param end ASCII结束值
         * @param letters 是否包含字母
         * @param numbers 是否包含数字
         * @return 随机字符串
         */
        public static String random(int count, int start, int end, boolean letters, boolean numbers) {
            return random(count, start, end, letters, numbers, null, RANDOM);
        }

        /**
         * 从指定字符集中生成随机字符串
         * @param count 字符串长度
         * @param chars 字符集
         * @return 随机字符串
         */
        public static String random(int count, String chars) {
            if (chars == null || chars.isEmpty()) {
                throw new IllegalArgumentException("字符集不能为空");
            }
            return random(count, chars.toCharArray());
        }

        /**
         * 从指定字符数组中生成随机字符串
         * @param count 字符串长度
         * @param chars 字符数组
         * @return 随机字符串
         */
        public static String random(int count, char[] chars) {
            if (chars == null || chars.length == 0) {
                throw new IllegalArgumentException("字符数组不能为空");
            }
            return random(count, 0, chars.length, false, false, chars, RANDOM);
        }

        /**
         * 使用安全随机数生成器生成字符串
         * @param count 字符串长度
         * @param chars 字符集
         * @return 安全随机字符串
         */
        public static String randomSecure(int count, String chars) {
            if (chars == null || chars.isEmpty()) {
                throw new IllegalArgumentException("字符集不能为空");
            }
            return random(count, 0, chars.length(), false, false, chars.toCharArray(), SECURE_RANDOM);
        }

        /**
         * 完整的随机字符串生成实现
         */
        private static String random(int count, int start, int end, boolean letters, boolean numbers,
                                     char[] chars, Random random) {
            if (count == 0) {
                return "";
            }
            if (count < 0) {
                throw new IllegalArgumentException("长度不能为负数: " + count);
            }

            // 处理字符集
            if (chars == null) {
                if (start == 0 && end == 0) {
                    end = 'z' + 1;
                    start = ' ';
                }

                if (end <= start) {
                    throw new IllegalArgumentException("结束值必须大于起始值");
                }

                char[] buffer = new char[count];
                int gap = end - start;

                while (count-- != 0) {
                    char ch;
                    if (chars == null) {
                        ch = (char) (random.nextInt(gap) + start);
                    } else {
                        ch = chars[random.nextInt(gap) + start];
                    }

                    // 过滤字符
                    if ((letters && Character.isLetter(ch)) ||
                            (numbers && Character.isDigit(ch)) ||
                            (!letters && !numbers)) {
                        buffer[count] = ch;
                    } else {
                        count++;
                    }
                }
                return new String(buffer);
            } else {
                // 使用提供的字符集
                char[] buffer = new char[count];
                int charsLength = chars.length;

                for (int i = 0; i < count; i++) {
                    buffer[i] = chars[random.nextInt(charsLength)];
                }
                return new String(buffer);
            }
        }

        /**
         * 生成指定长度的随机十六进制字符串
         * @param count 字节长度（每个字节生成2个字符）
         * @return 十六进制字符串
         */
        public static String randomHex(int count) {
            if (count <= 0) {
                return "";
            }

            byte[] bytes = new byte[count];
            SECURE_RANDOM.nextBytes(bytes);

            StringBuilder hexString = new StringBuilder(count * 2);
            for (byte b : bytes) {
                hexString.append(String.format("%02x", b));
            }
            return hexString.toString();
        }

        /**
         * 生成UUID风格的随机字符串
         * @return UUID风格字符串
         */
        public static String randomUUID() {
            return randomHex(4) + "-" +
                    randomHex(2) + "-" +
                    randomHex(2) + "-" +
                    randomHex(2) + "-" +
                    randomHex(6);
        }

        /**
         * 生成随机密码（安全增强版）
         * @param length 密码长度
         * @return 随机密码
         */
        public static String randomPassword(int length) {
            if (length < 8) {
                throw new IllegalArgumentException("密码长度至少为8位");
            }

            // 确保包含大写字母、小写字母、数字和特殊字符
            String uppercase = random(1, ALPHA_UPPER);
            String lowercase = random(1, ALPHA_LOWER);
            String digit = random(1, NUMERIC);
            String special = random(1, "!@#$%^&*");

            // 生成剩余部分
            String remaining = randomSecure(length - 4, SAFE_ALPHANUMERIC + "!@#$%^&*");

            // 组合并打乱顺序
            String combined = uppercase + lowercase + digit + special + remaining;
            return shuffle(combined);
        }

        /**
         * 打乱字符串顺序
         * @param str 原始字符串
         * @return 打乱后的字符串
         */
        public static String shuffle(String str) {
            if (str == null || str.isEmpty()) {
                return str;
            }

            char[] chars = str.toCharArray();
            for (int i = chars.length - 1; i > 0; i--) {
                int index = SECURE_RANDOM.nextInt(i + 1);
                // 交换
                char temp = chars[index];
                chars[index] = chars[i];
                chars[i] = temp;
            }
            return new String(chars);
        }

}
